package org.jeecg.modules.geo.service.impl;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.modules.core.constant.YesOrNotEnum;
import org.jeecg.modules.core.util.BimDateUtil;
import org.jeecg.modules.core.util.BimStringUtil;
import org.jeecg.modules.geo.core.constant.BimGeoRequestDataMethod;
import org.jeecg.modules.geo.core.constant.BimGeoRequestMethod;
import org.jeecg.modules.geo.core.constant.ExpireOffsetType;
import org.jeecg.modules.geo.core.constant.ExpireType;
import org.jeecg.modules.geo.entity.BimGeoApp;
import org.jeecg.modules.geo.model.BimGeoAppAuthConfig;
import org.jeecg.modules.geo.service.IBimGeoAppAuthService;
import org.jeecg.modules.geo.service.IBimGeoAppService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;

@Service
@Slf4j
public class BimGeoAppAuthServiceImpl implements IBimGeoAppAuthService {

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private IBimGeoAppService bimGeoAppService;

    @Override
    public String auth(Integer appId) {
        String token = (String) redisUtil.get(CommonConstant.PREFIX_BIM_GEO_APP_TOKEN + appId);
        if (StrUtil.isBlank(token)) {
            initAuth(appId);
            token = (String) redisUtil.get(CommonConstant.PREFIX_BIM_GEO_APP_TOKEN + appId);
        }
        return token;
    }

    /**
     * 初始化token
     */
    @Override
    public void initAuth(Integer appId) {
        // 未开启鉴权
        BimGeoAppAuthConfig authConfig = bimGeoAppService.getAuthConfig(appId);
        if (authConfig == null || YesOrNotEnum.N.getCode().equals(authConfig.getAuthEnableFlag())) {
            log.info("无需鉴权，appId=" + appId);
            return;
        }
        BimGeoApp bimGeoApp = bimGeoAppService.getById(appId);
        // 获取request
        HttpRequest request = this.getRequest(authConfig, bimGeoApp);
        // 请求
        HttpResponse response = request.execute();
        String body = response.body();
        if (org.apache.commons.lang3.StringUtils.isBlank(body)) {
            log.error("获取授权响应信息为空，appId=" + appId);
            return;
        }
        // 解析token
        String token = BimStringUtil.parsePath(body, authConfig.getTokenPath());
        if (org.apache.commons.lang3.StringUtils.isBlank(token)) {
            return;
        }
        // token前缀
        String tokenPrefix = StringUtils.isEmpty(authConfig.getTokenPrefix()) ? "" : authConfig.getTokenPrefix();
        token = tokenPrefix + token;
        //获取过期时间
        Date expireDate = this.getExpireDate(body, authConfig);
        //获取缓存秒数
        long second = DateUtil.between(new Date(), expireDate, DateUnit.SECOND);
        second = second - 2*60*60; //将缓存时间提前1小时,小于不保存
        if (second > 0) {
            redisUtil.set(CommonConstant.PREFIX_BIM_GEO_APP_TOKEN + appId, token, second);
        }
    }


    /**
     * 获取过期时间
     */
    private Date getExpireDate(String body, BimGeoAppAuthConfig authConfig) {
        Date result = new Date();
        // 过期日期类型
        Integer expireType = authConfig.getExpireType();
        if (expireType != null && !ExpireType.NONE.getValue().equals(expireType)) {
            // 解析过期时间
            String expireStr = BimStringUtil.parsePath(body, authConfig.getExpirePath());
            // 过期日期的类型为时间戳
            if (ExpireType.TIMESTAMP_MS.getValue().equals(expireType)) {
                result = new Date(Long.parseLong(expireStr));
            } else if (ExpireType.STRING.getValue().equals(expireType)) {
                // 过期日期的类型为字符串
                result = BimDateUtil.parse(expireStr, authConfig.getExpirePattern());
            }
        }

        // 偏移量类型
        Integer expireOffsetType = authConfig.getExpireOffsetType();
        // 过期偏移量解析
        String expireOffset = BimStringUtil.parsePath(body, authConfig.getExpireOffsetPath());

        try {
            if (expireOffsetType != null && !ExpireOffsetType.NONE.getValue().equals(expireOffsetType)) {
                if (ExpireOffsetType.OFFSET_DAY.getValue().equals(expireOffsetType)) {
                    // 天数偏移
                    result = BimDateUtil.offset(Calendar.HOUR_OF_DAY, result, Integer.valueOf(expireOffset));
                } else if (ExpireOffsetType.OFFSET_HOUR.getValue().equals(expireOffsetType)) {
                    // 小时偏移
                    result = BimDateUtil.offset(Calendar.HOUR, result, Integer.valueOf(expireOffset));
                } else if (ExpireOffsetType.OFFSET_MINUTE.getValue().equals(expireOffsetType)) {
                    // 分钟偏移
                    result = BimDateUtil.offset(Calendar.MINUTE, result, Integer.valueOf(expireOffset));
                } else if (ExpireOffsetType.OFFSET_SECOND.getValue().equals(expireOffsetType)) {
                    // 秒偏移
                    result = BimDateUtil.offset(Calendar.SECOND, result, Integer.valueOf(expireOffset));
                } else if (ExpireOffsetType.OFFSET_MILLISECOND.getValue().equals(expireOffsetType)) {
                    //毫秒偏移
                    result = BimDateUtil.offset(Calendar.MILLISECOND, result, Integer.valueOf(expireOffset));
                }
            }
        } catch (NumberFormatException e) {
            result = DateUtil.parse(expireOffset, DatePattern.NORM_DATETIME_PATTERN);
        }
        return result;
    }

    /**
     * 获取Request
     */
    private HttpRequest getRequest(BimGeoAppAuthConfig authConfig, BimGeoApp bimGeoApp) {
        // 账户信息
        HashMap<String, Object> formData = new HashMap<>();
        formData.put(authConfig.getAccountKey(), authConfig.getAccountValue());
        formData.put(authConfig.getPasswordKey(), authConfig.getPasswordValue());
        HttpRequest request = new HttpRequest(bimGeoApp.getApiUrl() + authConfig.getAuthPath());
        // 请求方式
        request.method(BimGeoRequestMethod.methodOf(authConfig.getAuthMethod()));
        // 数据传输方式
        if (BimGeoRequestDataMethod.FORM.getValue().equals(authConfig.getDataMethod())) {
            request.form(formData);
        } else {
            request.body(JSONUtil.parse(formData).toString());
        }
        // 超时时间
        if (authConfig.getTtl() != null) {
            request.timeout(authConfig.getTtl());
        }
        return request;
    }

}
